package com.suray.wcs.service.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.suray.basic.wcs.path.core.Node;
import com.suray.basic.wcs.plc.core.Plc;
import com.suray.basic.wcs.plc.enums.Location;
import com.suray.basic.wcs.plc.enums.Network;
import com.suray.basic.wcs.plc.pojo.DeviceBase;
import com.suray.basic.wcs.utils.Coord;
import com.suray.commin.core.utils.SpringContextHolder;
import com.suray.commin.core.utils.StringUtils;
import com.suray.system.run.random.code.thread.RunForGCodeThread;
import com.suray.wcs.res.msgparse.HeartSendBean;
import com.suray.wcs.service.core.util.LockNodeManager;
import com.suray.wcs.service.core.util.SysConfigUtil;
import com.suray.wcs.service.init.SystemInit;
import com.suray.wcs.service.pojo.Rgv;
import com.suray.wcs.service.scheduling.RgvTaskTimer;
import com.suray.wcs.service.system.entity.RgvDB;
import com.suray.wcs.service.system.entity.WareHouseDB;
import com.suray.wcs.service.system.mapper.DeviceManagerMapper;
import com.suray.wcs.service.system.service.IDeviceManagerService;
import com.suray.wcs.service.thread.*;
import com.suray.wcs.service.wmsconnect.ReturnMsgDevice;
import org.apache.shiro.util.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

@Service
public class DeviceManagerServiceImpl extends ServiceImpl<DeviceManagerMapper, RgvDB> implements IDeviceManagerService {
    private static final Integer RGV = 1;
    private static final Integer LIFTER = 2;
    @Autowired
    DeviceManagerMapper deviceManagerMapper;

    /**
     * 条件查询小车信息
     *
     * @return
     */
    @Override
    public List<RgvDB> getRgvList(RgvDB rgv) {
        QueryWrapper<RgvDB> queryWrapper = new QueryWrapper();
        if (rgv.getRgvNo() != null) {
            queryWrapper.lambda().eq(RgvDB::getRgvNo, rgv.getRgvNo());
        }
        if (rgv.getOnline() != null) {
            queryWrapper.lambda().eq(RgvDB::getOnline, rgv.getOnline());
        }
        if (!StringUtils.isEmpty(rgv.getLocation())) {
            queryWrapper.lambda().likeLeft(RgvDB::getLocation, rgv.getLocation() + ")");
        }
        if (rgv.getIsAutoCharge() != null) {
            queryWrapper.lambda().eq(RgvDB::getIsAutoCharge, rgv.getIsAutoCharge());
        }
        List<RgvDB> rgvDBS = deviceManagerMapper.selectList(queryWrapper);
        Collections.sort(rgvDBS, Comparator.comparing(RgvDB::getRgvNo));
        if (!CollectionUtils.isEmpty(rgvDBS)) {
            for (RgvDB rgvDB : rgvDBS) {
                ArrayList<Integer> xlist = new ArrayList<>();
                ArrayList<Integer> ylist = new ArrayList<>();
                ArrayList<Integer> zlist = new ArrayList<>();
                if (StringUtils.isNotEmpty(rgvDB.getXRegion())) {
                    for (String x : rgvDB.getXRegion().split("-")) {
                        if (x != null) {
                            xlist.add(Integer.parseInt(x));
                        } else {
                            log.warn("查询小车信息时，工作区域X存在空");
                        }
                    }
                }
                if (StringUtils.isNotEmpty(rgvDB.getYRegion())) {
                    for (String y : rgvDB.getYRegion().split("-")) {
                        if (y != null) {
                            ylist.add(Integer.parseInt(y));
                        } else {
                            log.warn("查询小车信息时，工作区域Y存在空");
                        }
                    }
                }

                if (StringUtils.isNotEmpty(rgvDB.getZRegion())) {
                    for (String z : rgvDB.getZRegion().split("-")) {
                        if (z != null) {
                            zlist.add(Integer.parseInt(z));
                        } else {
                            log.warn("查询小车信息时，工作区域Z存在空");
                        }
                    }
                }
                rgvDB.setXRegionList(xlist);
                rgvDB.setYRegionList(ylist);
                rgvDB.setZRegionList(zlist);
            }
        }
        // 返回结果
        return rgvDBS;
    }

    /**
     * 更新小车信息
     *
     * @param rgvdb
     * @return
     */
    public boolean updateRgv(RgvDB rgvdb) {
        StringBuffer sbx = new StringBuffer();
        StringBuffer sby = new StringBuffer();
        StringBuffer sbz = new StringBuffer();
        rgvdb.getXRegionList().forEach(x -> sbx.append(x + "-"));
        rgvdb.getYRegionList().forEach(y -> sby.append(y + "-"));
        rgvdb.getZRegionList().forEach(z -> sbz.append(z + "-"));
        if (!"".contentEquals(sbx)) {
            rgvdb.setXRegion(sbx.deleteCharAt(sbx.lastIndexOf("-")) + "");
        }
        if (!"".contentEquals(sby)) {
            rgvdb.setYRegion(sby.deleteCharAt(sby.lastIndexOf("-")) + "");
        }
        if (!"".contentEquals(sbz)) {
            rgvdb.setZRegion(sbz.deleteCharAt(sbz.lastIndexOf("-")) + "");
        }

        boolean success = this.updateById(rgvdb);
        // 修改成功之后修改RGVS列表中的rgv
        if (success) {
            Rgv rgv = SystemInit.getByRgvNo(rgvdb.getRgvNo());
            rgv.setRgvDB(rgvdb);
            List<Node> nodes = new ArrayList<>();
            nodes.add(rgvdb.getLocationNode());
            Set<Coord> unlockSet = new HashSet<>(nodes);
            LockNodeManager.addLockedNodes(unlockSet, rgv);// 锁定修改后的点
        }
        return success;
    }

    /**
     * 添加车辆
     *
     * @param rgvDB
     * @return
     */
    public boolean add(RgvDB rgvDB) {
        rgvDB.setMileage(0);
        if (rgvDB.getAssignBatterySize() == null) {
            rgvDB.setAssignBatterySize(50);
        }
        if (rgvDB.getXRegionList() != null) {
            StringBuffer sbx = new StringBuffer();
            rgvDB.getXRegionList().forEach(x -> sbx.append(x + "-"));
            if (!"".contentEquals(sbx)) {
                rgvDB.setXRegion(sbx.deleteCharAt(sbx.lastIndexOf("-")) + "");
            }
        }
        if (rgvDB.getYRegionList() != null) {
            StringBuffer sby = new StringBuffer();
            rgvDB.getYRegionList().forEach(y -> sby.append(y + "-"));
            if (!"".contentEquals(sby)) {
                rgvDB.setYRegion(sby.deleteCharAt(sby.lastIndexOf("-")) + "");
            }
        }
        if (rgvDB.getZRegionList() != null) {
            StringBuffer sbz = new StringBuffer();
            rgvDB.getZRegionList().forEach(z -> sbz.append(z + "-"));
            if (!"".contentEquals(sbz)) {
                rgvDB.setZRegion(sbz.deleteCharAt(sbz.lastIndexOf("-")) + "");
            }
        }
        boolean success = this.save(rgvDB);
        // 新增后向RGVS中新增rgv
        if (success) {
            WareHouseDB wareHouseDB = SpringContextHolder.getBean(WareHouseDBServiceImpl.class).getCurWareHouseDB();
            Boolean sonRgvDirectionX = wareHouseDB.getSonRgvDirectionX();
            Boolean sonRgvDirectionY = wareHouseDB.getSonRgvDirectionY();
            int mapVersion = SpringContextHolder.getBean(WareHouseDBServiceImpl.class).getCurWareHouseDB().getMapVersion();
            SystemInit.newRgv(rgvDB, mapVersion, sonRgvDirectionX, sonRgvDirectionY);
        }
        return success;

    }

    /**
     * 检测小车编号是否重复
     *
     * @param rgvdb
     * @return true 编号重复，false 编号未重复
     */
    public boolean checkRgvNo(RgvDB rgvdb) {
        if (rgvdb.getRgvId() == null) {// 新增
            QueryWrapper<RgvDB> queryWrapper = new QueryWrapper<>();
            queryWrapper.lambda().eq(RgvDB::getRgvNo, rgvdb.getRgvNo());
            int count = this.count(queryWrapper);
            return count >= 1;
        }
        // 修改
        RgvDB oldRgvDB = this.getById(rgvdb.getRgvId());
        if (oldRgvDB.getRgvNo().equals(rgvdb.getRgvNo())) {
            return false;
        } else {
            QueryWrapper<RgvDB> queryWrapper = new QueryWrapper<>();
            queryWrapper.lambda().eq(RgvDB::getRgvNo, rgvdb.getRgvNo());
            return this.count(queryWrapper) >= 1;
        }
    }

    /**
     * 检测小车位置是否重复
     *
     * @param rgvdb
     * @return true 位置重复，false 位置未重复
     */
    public boolean checkRgvLocation(RgvDB rgvdb) {
        Node node = Node.parseGrid(rgvdb.getLocation());
        QueryWrapper<RgvDB> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(RgvDB::getLocation, node.toString()).ne(RgvDB::getRgvId, rgvdb.getRgvId());
        int size = this.count(queryWrapper);
        if (size > 0) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 检测小车缓存位置是否重复
     *
     * @param rgvdb
     * @return true 编号重复，false 编号未重复
     */
    public boolean checkRgvFreeLocation(RgvDB rgvdb) {
        Node node = Node.parseGrid(rgvdb.getFreeLocation());
        QueryWrapper<RgvDB> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(RgvDB::getFreeLocation, node.toString()).ne(RgvDB::getRgvId, rgvdb.getRgvId());
        int size = this.count(queryWrapper);
        if (size > 0) {
            return true;
        } else {
            return false;
        }
    }

    @Override
    public void fillDevicesIdNotNullTypeNull(List<ReturnMsgDevice> devices, Integer deviceId, Integer deviceType) {
        forIdNotNullRGVS(devices, deviceId, RGV);
        forIdNotNullLifter(devices, deviceId, LIFTER);
    }

    @Override
    public void fillDevicesIdNotNullTypeNotNull(List<ReturnMsgDevice> devices, Integer deviceId, Integer deviceType) {
        if (deviceType.equals(RGV)) {
            forIdNotNullRGVS(devices, deviceId, deviceType);
        } else if (deviceType.equals(LIFTER)) {
            forIdNotNullLifter(devices, deviceId, deviceType);
        }
    }

    @Override
    public void fillDevicesIdNullTypeNull(List<ReturnMsgDevice> devices, Integer deviceType) {
        forIdNullRGVS(devices);
        forIdNullLifter(devices, LIFTER);
    }

    @Override
    public void fillDevicesIdNullTypeNotNull(List<ReturnMsgDevice> devices, Integer deviceType) {
        if (deviceType.equals(RGV)) {
            forIdNullRGVS(devices);
        } else if (deviceType.equals(LIFTER)) {
            forIdNullLifter(devices, deviceType);
        }
    }

    private void forIdNullLifter(List<ReturnMsgDevice> devices, Integer deviceType) {
        if (!CollectionUtils.isEmpty(Plc.deviceLifterCoordMap)) {
            for (Map.Entry<Coord, DeviceBase> entry : Plc.deviceLifterCoordMap.entrySet()) {
                DeviceBase deviceBase = entry.getValue();
                if (Location.INSIDE.equals(deviceBase.getLocation())) {
                    Coord coord = entry.getKey();
                    ReturnMsgDevice re = new ReturnMsgDevice();
                    re.setDeviceNo(deviceBase.getDeviceNo());
                    re.setDeviceStatus(Network.ON_LINE.getNetWorkNum());
                    re.setDeviceType(deviceType);
                    re.setLocation(coord.toString());
                    devices.add(re);
                }
            }
        }
    }

    private void forIdNullRGVS(List<ReturnMsgDevice> devices) {
        if (!CollectionUtils.isEmpty(SystemInit.RGVS)) {
            for (Rgv rgv : SystemInit.RGVS) {
                ReturnMsgDevice re = new ReturnMsgDevice();
                re.setDeviceNo(rgv.getRgvDB().getRgvNo());
                re.setDeviceStatus(rgv.getRgvStatus().getRgvStatus());
                re.setDeviceType(RGV);
                re.setLocation(rgv.getCurLocationStr());
                re.setDeviceInfo(rgv.getErrorMessage());
                re.setBattery(rgv.getBattery());
                devices.add(re);
            }
        }
    }

    private void forIdNotNullLifter(List<ReturnMsgDevice> devices, Integer deviceId, Integer deviceType) {
        if (!CollectionUtils.isEmpty(Plc.deviceLifterCoordMap)) {
            for (Map.Entry<Coord, DeviceBase> entry : Plc.deviceLifterCoordMap.entrySet()) {
                DeviceBase deviceBase = entry.getValue();
                if (deviceId.equals(deviceBase.getDeviceNo())) {
                    if (Location.INSIDE.equals(deviceBase.getLocation())) {
                        Coord coord = entry.getKey();
                        ReturnMsgDevice re = new ReturnMsgDevice();
                        re.setDeviceNo(deviceBase.getDeviceNo());
                        re.setDeviceStatus(Network.ON_LINE.getNetWorkNum());
                        re.setDeviceType(deviceType);
                        re.setLocation(coord.toString());
                        devices.add(re);
                    }
                }
            }
        }
    }

    private void forIdNotNullRGVS(List<ReturnMsgDevice> devices, Integer deviceId, Integer deviceType) {
        if (!CollectionUtils.isEmpty(SystemInit.RGVS)) {
            for (Rgv rgv : SystemInit.RGVS) {
                if (deviceId.equals(rgv.getRgvDB().getRgvNo())) {
                    ReturnMsgDevice re = new ReturnMsgDevice();
                    re.setDeviceNo(rgv.getRgvDB().getRgvNo());
                    re.setDeviceStatus(rgv.getRgvStatus().getRgvStatus());
                    re.setDeviceType(deviceType);
                    re.setLocation(rgv.getCurLocationStr());
                    re.setBattery(rgv.getBattery());
                    devices.add(re);
                }
            }
        }
    }
}
